package com.github.framework.aop.intercept;

import java.lang.reflect.Method;
import java.util.List;

/**
 * @program: springv2
 * @description: 方法调用器
 * @author: Pop
 * @create: 2021-07-22 21:34
 **/
public class MethodInvocation {

    protected final Object proxy;

    protected final Object target;

    protected final Method method;

    protected Object[] arguments = new Object[0];

    private final Class<?> targetClass;

    protected final List<?> interceptorsAndDynamicMethodMatchers;

    private int currentInterceptorIndex = -1;

    public MethodInvocation(
            Object proxy, Object target, Method method,  Object[] arguments,
            Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {

        this.proxy = proxy;
        this.target = target;
        this.targetClass = targetClass;
        this.method = method;
        this.arguments = arguments;
        this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
    }

    public Object proceed() throws Throwable{
        //	We start with an index of -1 and increment early.
        //如果Interceptor执行完了，则执行joinPoint
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
//            return invokeJoinpoint();
            // 原Spring，这里也是直接反射调用 只不过是做了封装
            return this.method.invoke(this.target,this.arguments);
        }


        Object interceptorOrInterceptionAdvice =
                this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        if (interceptorOrInterceptionAdvice instanceof MethodInterceptor) {
            // Evaluate dynamic method matcher here: static part will already have
            // been evaluated and found to match.
            MethodInterceptor mi =
                    (MethodInterceptor) interceptorOrInterceptionAdvice;
            // 调用拦截器的逻辑
            return mi.invoke(this);
        }
        else {
            // 接着下一个拦截器
            return proceed();
        }
    }

}
